package cn.mesmile.workflow.process.service.impl;

import cn.mesmile.workflow.commom.Query;
import cn.mesmile.workflow.commom.R;
import cn.mesmile.workflow.constant.WorkFlowConstant;
import cn.mesmile.workflow.process.bo.OperationTaskBO;
import cn.mesmile.workflow.process.dto.WorkFlowNodeDTO;
import cn.mesmile.workflow.process.qo.WorkFlowQO;
import cn.mesmile.workflow.process.service.WorkFlowService;
import cn.mesmile.workflow.util.WorkFlowUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.constants.BpmnXMLConstants;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.impl.util.ExecutionGraphUtil;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zb
 * @Description
 */
@Slf4j
@Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS, readOnly = true)
@AllArgsConstructor
@Service
public class WorkFlowServiceImpl implements WorkFlowService {

    private final RepositoryService repositoryService;
    private final RuntimeService runtimeService;
    private final TaskService taskService;
    private final HistoryService historyService;
    private final IdentityService identityService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Deployment deploy() {
        Deployment deploy = repositoryService.createDeployment()
                .key("leave") // 流程定义key
                .name("请假流程") // 流程定义名称
                .category("hr") // 模型分类
                .addClasspathResource("leave.bpmn20.xml").deploy();
        return deploy;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ProcessInstance startProcessInstanceByDefId(String processDefId, Map<String, Object> variables) {
        // 设置流程发起人
        identityService.setAuthenticatedUserId(WorkFlowUtil.getCurrentUserId());
        // TODO 自定义逻辑，存入申请人的 id 和 名称
        variables.put(WorkFlowConstant.PROCESS_APPLY_USER, WorkFlowUtil.getCurrentUserId());
        variables.put(WorkFlowConstant.PROCESS_APPLY_USER_NAME, WorkFlowUtil.getCurrentUserName());

        ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefId, variables);
        String processInstanceId = processInstance.getProcessInstanceId();

//        runtimeService.setProcessInstanceName(processInstance.getId(),processInstance.getProcessDefinitionName());
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId);
        // 判断是否跳过第一个节点
        String skipNode = WorkFlowUtil.getProcessExtensionAttribute(bpmnModel, WorkFlowConstant.SKIP_FIRST_NODE);
        if (StringUtils.isNotBlank(skipNode) && Objects.equals("true", skipNode)) {
            List<Task> list = taskService.createTaskQuery().processInstanceId(processInstanceId).list();
            if (list != null && list.size() > 0) {
                list.forEach(task -> {
                    String taskId = task.getId();
                    // 添加评论
                    taskService.addComment(taskId, processInstanceId, WorkFlowConstant.AUTO_COMPLETED_TASK, WorkFlowConstant.AUTO_COMPLETED_TASK_DESCRIBE);
                    // 自动完成
                    taskService.complete(taskId);
                });
            }
        }

        return processInstance;
    }

    @Override
    public IPage<ProcessDefinition> listProcessDefinition(Query query, WorkFlowQO workFlowQO) {
        ProcessDefinitionQuery processDefinitionQuery =
                repositoryService.createProcessDefinitionQuery();
        String processDefName = workFlowQO.getProcessDefName();
        String processDefKey = workFlowQO.getProcessDefKey();
        String category = workFlowQO.getCategory();
        Boolean lastVersion = workFlowQO.getLastVersion();
        if (StringUtils.isNotBlank(processDefName)) {
            processDefinitionQuery.processDefinitionNameLike("%" + processDefName + "%");
        }
        if (StringUtils.isNotBlank(processDefKey)) {
            processDefinitionQuery.processDefinitionKey(processDefKey);
        }
        if (StringUtils.isNotBlank(category)) {
            processDefinitionQuery.processDefinitionCategory(category);
        }
        if (lastVersion != null && lastVersion) {
            processDefinitionQuery.latestVersion();
        }
        long total = processDefinitionQuery.count();
        Integer current = query.getCurrent();
        Integer size = query.getSize();
        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.listPage((current - 1) * size, size);
        Page<ProcessDefinition> page = Page.of(current, size, total);
        page.setRecords(processDefinitionList);
        return page;
    }

    @Override
    public IPage<Task> listTodoTask(Query query, WorkFlowQO workFlowQO) {
        // 查审批
        TaskQuery taskQuery = taskService.createTaskQuery()
                // todo 传入当前用户
                .taskCandidateOrAssigned(WorkFlowUtil.getCurrentUserId())
                .taskCandidateGroupIn(new ArrayList<>()) // 候选组
                .active() // 激活的
                .orderByTaskCreateTime().desc();

        String processDefName = workFlowQO.getProcessDefName();
        String processDefKey = workFlowQO.getProcessDefKey();
        String taskName = workFlowQO.getTaskName();
        String applyUser = workFlowQO.getApplyUser();
        Date startDate = workFlowQO.getStartDate();
        Date endDate = workFlowQO.getEndDate();
        List<String> categoryList = workFlowQO.getCategoryList();
        if (StringUtils.isNotBlank(processDefName)) {
            taskQuery.processDefinitionNameLike("%" + processDefName + "%");
        }
        if (StringUtils.isNotBlank(processDefName)) {
            taskQuery.processDefinitionKey(processDefKey);
        }
        if (StringUtils.isNotBlank(taskName)) {
            taskQuery.taskName(taskName);
        }
        if (categoryList != null && categoryList.size() > 0) {
            taskQuery.processCategoryIn(categoryList);
        }
        if (StringUtils.isNotBlank(applyUser)) {
            taskQuery.processVariableValueEquals(WorkFlowConstant.PROCESS_APPLY_USER, applyUser);
        }
        if (startDate != null) {
            taskQuery.taskCreatedAfter(startDate);
        }
        if (endDate != null) {
            taskQuery.taskCreatedBefore(endDate);
        }
        long count = taskQuery.count();

        Integer current = query.getCurrent();
        Integer size = query.getSize();
        List<Task> tasks = taskQuery.listPage((current - 1) * size, size);
        Page<Task> page = Page.of(current, size, count);
        page.setRecords(tasks);
        return page;
    }

    @Override
    public IPage<Task> listClaimTask(Query query, WorkFlowQO workFlowQO) {
        // 查【候选】
        TaskQuery taskQuery = taskService.createTaskQuery()
                // 当前用户是否存在于候选人之内
                .taskCandidateUser(WorkFlowUtil.getCurrentUserId())
                // 查询当前用户所在的候选组
                .taskCandidateGroupIn(new ArrayList<>())
                .active()
                .orderByTaskCreateTime()
                .desc();
        String processDefName = workFlowQO.getProcessDefName();
        String processDefKey = workFlowQO.getProcessDefKey();
        String taskName = workFlowQO.getTaskName();
        String applyUser = workFlowQO.getApplyUser();
        Date startDate = workFlowQO.getStartDate();
        Date endDate = workFlowQO.getEndDate();
        List<String> categoryList = workFlowQO.getCategoryList();
        if (StringUtils.isNotBlank(processDefName)) {
            taskQuery.processDefinitionNameLike("%" + processDefName + "%");
        }
        if (StringUtils.isNotBlank(processDefName)) {
            taskQuery.processDefinitionKey(processDefKey);
        }
        if (StringUtils.isNotBlank(taskName)) {
            taskQuery.taskName(taskName);
        }
        if (categoryList != null && categoryList.size() > 0) {
            taskQuery.processCategoryIn(categoryList);
        }
        if (StringUtils.isNotBlank(applyUser)) {
            taskQuery.processVariableValueEquals(WorkFlowConstant.PROCESS_APPLY_USER, applyUser);
        }
        if (startDate != null) {
            taskQuery.taskCreatedAfter(startDate);
        }
        if (endDate != null) {
            taskQuery.taskCreatedBefore(endDate);
        }
        long count = taskQuery.count();

        Integer current = query.getCurrent();
        Integer size = query.getSize();
        List<Task> tasks = taskQuery.listPage((current - 1) * size, size);
        Page<Task> page = Page.of(current, size, count);
        page.setRecords(tasks);
        return page;
    }

    @Override
    public IPage<HistoricProcessInstance> listDoneProcess(Query query, WorkFlowQO workFlowQO) {
        HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery()
                // TODO 传入当前用户  查询当前用户所涉及到的流程实例
                .involvedUser(WorkFlowUtil.getCurrentUserId())
                .orderByProcessInstanceStartTime()
                .desc();
        String processDefName = workFlowQO.getProcessDefName();
        String processDefKey = workFlowQO.getProcessDefKey();
        String category = workFlowQO.getCategory();
        String applyUser = workFlowQO.getApplyUser();
        Date startDate = workFlowQO.getStartDate();
        Date endDate = workFlowQO.getEndDate();
        if (StringUtils.isNotBlank(processDefName)) {
            processInstanceQuery.processDefinitionName("%" + processDefName + "%");
        }
        if (StringUtils.isNotBlank(processDefKey)) {
            processInstanceQuery.processDefinitionKey(processDefKey);
        }
        if (StringUtils.isNotBlank(category)) {
            processInstanceQuery.processDefinitionCategory(category);
        }
        if (StringUtils.isNotBlank(applyUser)) {
            processInstanceQuery.variableValueEquals(WorkFlowConstant.PROCESS_APPLY_USER, applyUser);
        }
        if (startDate != null) {
            processInstanceQuery.startedAfter(startDate);
        }
        if (endDate != null) {
            processInstanceQuery.startedBefore(endDate);
        }
        long total = processInstanceQuery.count();
        Integer current = query.getCurrent();
        Integer size = query.getSize();

        List<HistoricProcessInstance> historicProcessInstances = processInstanceQuery.listPage((current - 1) * size, size);
        Page<HistoricProcessInstance> page = Page.of(current, size, total);
        page.setRecords(historicProcessInstances);
        return page;
    }

    @Override
    public IPage<HistoricProcessInstance> listSendProcess(Query query, WorkFlowQO workFlowQO) {
        HistoricProcessInstanceQuery historyQuery = historyService.createHistoricProcessInstanceQuery()
                // 传入当前用户
                .startedBy(WorkFlowUtil.getCurrentUserId())
                .orderByProcessInstanceStartTime().desc();
        String processDefName = workFlowQO.getProcessDefName();
        String processDefKey = workFlowQO.getProcessDefKey();
        String category = workFlowQO.getCategory();
        Date startDate = workFlowQO.getStartDate();
        Date endDate = workFlowQO.getEndDate();
        if (StringUtils.isNotBlank(processDefName)) {
            historyQuery.processDefinitionName("%" + processDefName + "%");
        }
        if (StringUtils.isNotBlank(processDefKey)) {
            historyQuery.processDefinitionKey(processDefKey);
        }
        if (StringUtils.isNotBlank(category)) {
            historyQuery.processDefinitionCategory(category);
        }
        if (startDate != null) {
            historyQuery.startedAfter(startDate);
        }
        if (endDate != null) {
            historyQuery.startedBefore(endDate);
        }
        long total = historyQuery.count();
        Integer current = query.getCurrent();
        Integer size = query.getSize();

        List<HistoricProcessInstance> historicProcessInstances = historyQuery.listPage((current - 1) * size, size);
        Page<HistoricProcessInstance> page = Page.of(current, size, total);
        page.setRecords(historicProcessInstances);
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R completeTask(OperationTaskBO operationTaskBO) {
        Boolean pass = operationTaskBO.getPass();
        String taskId = operationTaskBO.getTaskId();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return R.fail("当前任务不存在" + taskId);
        }
        if (pass == null || pass) {
            // 默认通过
            passTask(operationTaskBO, task);
        } else {
            // 拒绝/驳回
            rejectTask(task, operationTaskBO);
        }
        return R.data("操作成功");
    }

    @Override
    public void urgeTask(OperationTaskBO operationTaskBO) {
        String taskId = operationTaskBO.getTaskId();
        if (StringUtils.isNotBlank(taskId)) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null && StringUtils.isNotBlank(task.getAssignee())) {
                // todo 发送通知消息
                log.info(">>>>>>>>>>>> 发送通知消息: {}", task.getAssignee());

            }
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void transferTask(OperationTaskBO operationTaskBO) {
        String receiveUserId = operationTaskBO.getReceiveUserId();
        if (StringUtils.isBlank(receiveUserId)) {
            return;
        }
        String taskId = operationTaskBO.getTaskId();
        if (StringUtils.isNotBlank(taskId)) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                String comment = operationTaskBO.getComment();
                if (StringUtils.isNotBlank(comment)) {
                    String assignee = task.getAssignee();
                    String message = WorkFlowConstant.TRANSFER_TASK_DESCRIBE + ": " + assignee + " → " + receiveUserId + " " + WorkFlowUtil.getCurrentUserName() + " 操作";
                    // 添加转办评论
                    taskService.addComment(taskId, task.getProcessInstanceId(), WorkFlowConstant.TRANSFER_TASK, message);
                }
                // 设置任务归属
                taskService.setOwner(taskId, WorkFlowUtil.getCurrentUserId());
                // 指定任务审批人
                taskService.setAssignee(taskId, receiveUserId);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delegateTask(OperationTaskBO operationTaskBO) {
        String receiveUserId = operationTaskBO.getReceiveUserId();
        String taskId = operationTaskBO.getTaskId();
        if (StringUtils.isNoneBlank(receiveUserId, taskId)) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                if (StringUtils.isNotBlank(operationTaskBO.getComment())) {
                    String assignee = task.getAssignee();
                    String message = WorkFlowConstant.DELEGATE_TASK_DESCRIBE + ": " + assignee + " → " + receiveUserId + " " + WorkFlowUtil.getCurrentUserName() + " 操作";
                    // 添加转办评论
                    taskService.addComment(taskId, task.getProcessInstanceId(), WorkFlowConstant.DELEGATE_TASK, message);
                }
                // 设置任务 owner
                taskService.setOwner(taskId, WorkFlowUtil.getCurrentUserId());
                // 委托任务
                taskService.delegateTask(taskId, receiveUserId);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void terminationTask(OperationTaskBO operationTaskBO) {
        String taskId = operationTaskBO.getTaskId();
        if (StringUtils.isNotBlank(taskId)) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                String processDefinitionId = task.getProcessDefinitionId();
                String processInstanceId = task.getProcessInstanceId();
                if (StringUtils.isNotBlank(operationTaskBO.getComment())) {
                    String message = WorkFlowConstant.TERMINATION_TASK_DESCRIBE + ": " + WorkFlowUtil.getCurrentUserName() + " 操作";
                    // 添加终止评论
                    taskService.addComment(taskId, task.getProcessInstanceId(), WorkFlowConstant.TERMINATION_TASK, message);
                }
                // 查找结束节点
                List<EndEvent> endElementList = getEndFlowElement(processDefinitionId);
                if (endElementList.size() > 0) {
                    // 跳转到结束节点
                    goToTargetActivity(processInstanceId, endElementList.get(0).getId());
                }
            }
        }
    }

    @Override
    public void addMultiInstance(OperationTaskBO operationTaskBO) {
        String taskId = operationTaskBO.getTaskId();
        List<String> receiveUserIdList = operationTaskBO.getReceiveUserIdList();
        if (receiveUserIdList == null || receiveUserIdList.size() < 1) {
            return;
        }
        if (StringUtils.isNotBlank(taskId)) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                for (String receiveUserId : receiveUserIdList) {
                    if (StringUtils.isBlank(operationTaskBO.getComment())) {
                        String message = WorkFlowConstant.ADD_MULTI_INSTANCE_DESCRIBE + ": " + WorkFlowUtil.getCurrentUserName() + " 操作";
                        // 添加评论
                        taskService.addComment(taskId, task.getProcessInstanceId(), WorkFlowConstant.ADD_MULTI_INSTANCE, message);
                    }
                    String taskDefinitionKey = task.getTaskDefinitionKey();
                    String processInstanceId = task.getProcessInstanceId();
                    // 加签
                    runtimeService.addMultiInstanceExecution(taskDefinitionKey, processInstanceId, Collections.singletonMap("assignee", receiveUserId));
                }
            }
        }
    }

    @Override
    public void deleteMultiInstance(OperationTaskBO operationTaskBO) {
        String taskId = operationTaskBO.getTaskId();
        if (StringUtils.isNotBlank(taskId)) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                String message = WorkFlowConstant.DELETE_MULTI_INSTANCE_DESCRIBE + ": " + WorkFlowUtil.getCurrentUserName() + " 操作";
                // 添加评论
                taskService.addComment(taskId, task.getProcessInstanceId(), WorkFlowConstant.DELETE_MULTI_INSTANCE, message);
                // 减签
                runtimeService.deleteMultiInstanceExecution(task.getExecutionId(), false);
            }
        }
    }

    @Override
    public void rollbackTask(OperationTaskBO operationTaskBO) {
        String taskId = operationTaskBO.getTaskId();
        String targetNodeId = operationTaskBO.getTargetNodeId();
        if (StringUtils.isNoneBlank(taskId, targetNodeId)) {
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                String assignee = task.getAssignee();
                if (StringUtils.isBlank(assignee)){
                    this.claimTask(taskId);
                }
                String message = WorkFlowConstant.ROLL_BACK_TASK_DESCRIBE + ": " + WorkFlowUtil.getCurrentUserName() + " 操作";
                // 添加评论
                taskService.addComment(taskId, task.getProcessInstanceId(), WorkFlowConstant.ROLL_BACK_TASK, message);
                // 跳转
                goToTargetActivity(task.getProcessInstanceId(), targetNodeId);
            }
        }
    }

    @Override
    public void claimTask(String taskId) {
        if (StringUtils.isNotBlank(taskId)){
            Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
            if (task != null) {
                // 签收任务
                taskService.claim(taskId, WorkFlowUtil.getCurrentUserId());
            }
        }
    }

    @Override
    public List<WorkFlowNodeDTO> getBackNodeList(OperationTaskBO operationTaskBO) {
        String taskId = operationTaskBO.getTaskId();
        List<WorkFlowNodeDTO> result = new ArrayList<>(16);
        if (StringUtils.isBlank(taskId)){
            return result;
        }
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null){
            return result;
        }
        // 任务定义key 等于
        String taskDefinitionKey = task.getTaskDefinitionKey();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        Process mainProcess = bpmnModel.getMainProcess();
        // 当前节点
        FlowNode currentFlowElement = (FlowNode) mainProcess.getFlowElement(taskDefinitionKey, true);
        // 查询历史节点实例
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .finished()
                .orderByHistoricActivityInstanceEndTime().asc().list();
        List<String> activityIdList = activityInstanceList.stream()
                .filter(activityInstance ->
                        BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType()) || BpmnXMLConstants.ELEMENT_EVENT_START.equals(activityInstance.getActivityType()))
                .map(HistoricActivityInstance::getActivityId)
                .filter(activityId -> !taskDefinitionKey.equals(activityId))
                .distinct()
                .collect(Collectors.toList());
        for (String activityId : activityIdList) {
            // 回退到主流程的节点
            FlowNode toBackFlowElement = (FlowNode) mainProcess.getFlowElement(activityId, true);
            // 判断 【工具类判断是否可以从源节点 到 目标节点】
            Set<String> set = new HashSet<>();
            if (toBackFlowElement != null && ExecutionGraphUtil.isReachable(mainProcess,toBackFlowElement,currentFlowElement, set)) {
                WorkFlowNodeDTO workFlowNodeDTO = new WorkFlowNodeDTO();
                workFlowNodeDTO.setNodeId(activityId);
                workFlowNodeDTO.setNodeName(toBackFlowElement.getName());
                result.add(workFlowNodeDTO);
            }
        }
        return result;
    }

    @Override
    public WorkFlowNodeDTO getPreBackNode(OperationTaskBO operationTaskBO) {
        String taskId = operationTaskBO.getTaskId();
        WorkFlowNodeDTO result = new WorkFlowNodeDTO();
        if (StringUtils.isBlank(taskId)){
            return result;
        }
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null){
            return result;
        }
        // 任务定义key 等于
        String taskDefinitionKey = task.getTaskDefinitionKey();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        Process mainProcess = bpmnModel.getMainProcess();
        // 当前节点
        FlowNode currentFlowElement = (FlowNode) mainProcess.getFlowElement(taskDefinitionKey, true);
        // 查询历史节点实例，按照时间降序排列
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .finished()
                .orderByHistoricActivityInstanceEndTime()
                .desc().list();
        for (HistoricActivityInstance activityInstance : activityInstanceList) {
            // 只过滤【用户任务】【开始】节点
            if (BpmnXMLConstants.ELEMENT_TASK_USER.equals(activityInstance.getActivityType()) || BpmnXMLConstants.ELEMENT_EVENT_START.equals(activityInstance.getActivityType())) {
                String activityId = activityInstance.getActivityId();
                if (!Objects.equals(taskDefinitionKey, activityId)) {
                    FlowNode backFlowElement = (FlowNode) mainProcess.getFlowElement(activityId, true);
                    Set<String> set = new HashSet<>();
                    if (backFlowElement != null && ExecutionGraphUtil.isReachable(mainProcess, backFlowElement, currentFlowElement, set)) {
                        result.setNodeId(activityId);
                        result.setNodeName(backFlowElement.getName());
                        return result;
                    }
                }
            }
        }
        return result;
    }

    /**
     * 查找主流程中的结束节点
     * @param processDefinitionId 流程定义id
     * @return
     */
    private List<EndEvent> getEndFlowElement(String processDefinitionId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        Process mainProcess = bpmnModel.getMainProcess();
        Collection<FlowElement> flowElements = mainProcess.getFlowElements();
        List<EndEvent> endElementList = new ArrayList<>(10);
        if (flowElements != null && flowElements.size() > 0) {
            for (FlowElement element : flowElements) {
                if (element instanceof EndEvent) {
                    endElementList.add((EndEvent) element);
                }
            }
        }
        return endElementList;
    }

    /**
     * 驳回/拒绝 操作
     *
     * @param task            当前任务
     * @param operationTaskBO 完成任务参数
     */
    private void rejectTask(Task task, OperationTaskBO operationTaskBO) {
        String processDefinitionId = task.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        // 找默认回退节点
        String processExtensionAttribute = WorkFlowUtil.getProcessExtensionAttribute(bpmnModel, WorkFlowConstant.ROLLBACK_NODE);
        if (StringUtils.isNotBlank(processExtensionAttribute) && Objects.equals("true", processExtensionAttribute)) {
            String processInstanceId = task.getProcessInstanceId();
            if (StringUtils.isNotBlank(operationTaskBO.getComment())) {
                // 添加驳回评论
                taskService.addComment(task.getId(), processInstanceId, WorkFlowConstant.REFUSE_TASK, operationTaskBO.getComment());
            }
            // 回退到指定节点
            goToTargetActivity(processInstanceId, processExtensionAttribute);
        } else {
            // todo 若没有默认回退节点，则回退到上一步

        }
    }

    /**
     * 流转到指定的节点
     *
     * @param processInstanceId 流程实例id
     * @param targetNodeId      目标节点id
     */
    private void goToTargetActivity(String processInstanceId, String targetNodeId) {
        List<Execution> list = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
        Set<String> currentActivityIds = list.stream().map(Execution::getActivityId).collect(Collectors.toSet());
        runtimeService.createChangeActivityStateBuilder()
                .moveActivityIdsToSingleActivityId(new ArrayList<>(currentActivityIds), targetNodeId)
                .changeState();
    }

    /**
     * 完成通过任务
     *
     * @param operationTaskBO 完成任务参数
     * @param task            当前任务
     */
    private void passTask(OperationTaskBO operationTaskBO, Task task) {
        String processInstanceId = task.getProcessInstanceId();
        String taskId = task.getId();
        if (StringUtils.isNotBlank(operationTaskBO.getComment())) {
            // 添加评论
            taskService.addComment(taskId, processInstanceId, operationTaskBO.getComment());
        }
        Map<String, Object> variables = operationTaskBO.getVariables();
        if (variables == null) {
            variables = new HashMap<>(2);
        }
        // 完成任务
        taskService.complete(taskId, variables);
    }


}
